量化交易策略——BIAS策略简单小试and加强版

2
回复
4070
查看
[复制链接]

294

主题

20

回帖

1380

积分

专栏作家

积分
1380
来源: 2019-7-17 22:24:20 显示全部楼层 |阅读模式
乖离率(BIAS)简称Y值,是移动平均(moving average)原理派生的一项技术指标,测试原理是建立在:如果股价偏离移动平均线太远,不管股价在移动平均线之上或之下,都有可能趋向平均线的这一条原理上。而乖离率则表示股价偏离趋向指标所占到的百分比值。
   
    计算方法:N期BIAS=(当日收盘价-N期平均收盘价)/N期平均收盘价*100%

    回测:

    资金:100000
    频率:日
    交易资产:平安银行
    手续费滑点采用平台默认
    采用13日bias值,买入卖出临界值为0.065,即bias<-0.065满仓买入,bias>0.065全仓卖出
   
    分析:

    信号设置较为简单,可以考虑和别的指标结合下。
    交易次数较少,每次都是全买全卖,买完了等好久都卖不出去的情况很容易出现,导致错过很多更好的买点。
    参数没有计算机优化。
    后期大趋势下,表现不好。
    由bias值与股价的图看出,bias值并没有明显领先股价做出变化。

收益与风险










源码:


  1. # 定义一个全局变量, 保存要操作的证券
  2. # 000001(股票:平安银行)
  3. security = '000001.XSHE'
  4. # 初始化此策略
  5. # 设置我们要操作的股票池, 这里我们只操作一支股票
  6. set_universe([security])

  7. # 每个单位时间(如果按天回测,则每天调用一次,如果按分钟,则每分钟调用一次)调用一次
  8. def handle_data(context, data):
  9.     # 取得过去十三天的平均价格
  10.     average_price = data[security].mavg(13)
  11.     # 取得当前价格
  12.     current_price = data[security].price
  13.     # 取得当前的现金
  14.     cash = context.portfolio.cash
  15.     # 计算BIAS值
  16.     bias=(current_price-average_price)/average_price
  17.     # 设置BIAS操作临界值
  18.     bias_operationvalue=0.065;
  19.     # 如果BIAS值小于-BIAS操作临界值,买入
  20.     if bias < -1*bias_operationvalue:
  21.         # 计算可以买多少只股票
  22.         number_of_shares = int(cash/current_price)
  23.         # 购买量大于0时,下单
  24.         if number_of_shares > 0:
  25.             # 买入股票
  26.             order(security, +number_of_shares)
  27.             # 记录这次买入
  28.             log.info("Buying %s" % (security))
  29.     # 如果BIAS大于BIAS操作临界值,卖出
  30.     elif bias > bias_operationvalue and context.portfolio.positions[security].amount > 0:
  31.         # 卖出所有股票,使这只股票的最终持有量为0
  32.         order_target(security, 0)
  33.         # 记录这次卖出
  34.         log.info("Selling %s" % (security))
  35.     # 画出当前的价格
  36.     record(stock_price=data[security].price)
  37.     record(bias=bias*20+7)
复制代码

bias策略加强版

    主要变化

    1.加入了多股票方法,每隔一个周期开始前,结算上一周期未卖出的股票,从股票池(此次选的沪深300)里挑选一些股票(挑选标准此次选的是价格超过5日均线2%),在一个周期内每个单位时间循环访问每个挑选出来的股票,进行判断是否买入(判断标准是13日bias值<-0.06)或卖出(判断标准是13日bias值>0.06).

    2.加入了止损,每只股票亏损超过20%,则止损。

    3.加入了仓位管理,将资金平均分配给每个股票,每个股票依然只能是进行满仓空仓操作。

    4.加入了胜率统计,在卖的时候判断,盈利则成功,亏损则失败,胜率算法为,成功次数除以成功与失败之和。在日志里输出,此次的胜率是64%。

    核心代码

#初始化
def initialize(context):
    ......
#每个单位时间执行一次handle_data内的指令
def handle_data(context, data):
    #如果是一个新的周期
    if g.i%g.period==0:
        #清算所有未卖出的股票
        clear(context, data)
        #从股票池中挑选股票
        findstock(context, data)
    # 循环股票池
    for security in g.buystocks:
         #进行股票交易


收益与风险











源码:
  1. # 定义一个全局变量, 保存要操作的证券
  2. def initialize(context):
  3.     #设置股票池
  4.     context.stocks = get_index_stocks('000300.XSHG')
  5.     set_universe(context.stocks)
  6.     #设置最多挑选的股票数量
  7.     g.max_stock=10
  8.     #平均分配股票的可用资金
  9.     g.max_use_cash=context.portfolio.cash/g.max_stock
  10.     #设置变量,记录操作成功与失败次数
  11.     g.win=0.0
  12.     g.lose=0.0
  13.     #计时器
  14.     g.i=-1;
  15.     #股票池中选择出的股票列表
  16.     g.buystocks = []
  17.     #更新股票列表周期
  18.     g.period=60

  19. # 每个单位时间(如果按天回测,则每天调用一次,如果按分钟,则每分钟调用一次)调用一次
  20. def handle_data(context, data):
  21.     g.i=g.i+1
  22.     #判断是否为一个新周期
  23.     if g.i%g.period==0:
  24.         #清算所有未卖出的股票
  25.         clear(context, data)
  26.         #从股票池中挑选股票
  27.         findstock(context, data)
  28.     # 循环股票池
  29.     for security in g.buystocks:
  30.         # 得到该股票当前价格
  31.         current_price = data[security].price
  32.         #得到十三日均价
  33.         avg = data[security].mavg(13)
  34.         #计算bias值
  35.         bias = (current_price-avg)/avg
  36.         #计算持仓成本
  37.         current_avgcost = context.portfolio.positions[security].avg_cost
  38.         #计算当前股票的盈利状况
  39.         if context.portfolio.positions[security].amount > 0:
  40.             r_ratio=(current_price-current_avgcost)/current_avgcost
  41.         else:
  42.             r_ratio=0
  43.    
  44.         # 如果bias值小于-0.06,且仓位为空,则买入
  45.         if bias < -0.06 and context.portfolio.positions[security].amount == 0:
  46.             # 计算可以买多少只股票
  47.             amount = int(g.max_use_cash / current_price)
  48.             # 下入买入单
  49.             order(security, amount)
  50.         # 如果bias值大于0.06,且仓位非空,则卖出
  51.         elif (r_ratio<-0.2 or bias > 0.06) and context.portfolio.positions[security].amount > 0:
  52.             # 卖出所有股票,使这只股票的最终持有量为0
  53.             orderfail=order_target(security, 0)
  54.             if orderfail!=None:#防止订单无效,如停牌、没钱买等
  55.                 #统计胜率
  56.                 winorlose(r_ratio)
  57.     #计算操作次数
  58.     times=g.win+g.lose
  59.     #取得当前时间
  60.     date = context.current_dt.strftime("%Y-%m-%d")
  61.     #在最后一个单位时间,清空仓位,并在日志中输出成功次数,失败次数,与胜率
  62.     if date=='2015-09-30':
  63.         clear(context, data
  64.         if times !=0:
  65.             print(g.win,g.lose,g.win/times)
  66.             
  67.    
  68. def clear(context, data):
  69.     for security in g.buystocks:
  70.         # 得到该股票当前价格
  71.         current_price = data[security].price
  72.         #计算持仓成本
  73.         current_avgcost = context.portfolio.positions[security].avg_cost
  74.         
  75.         #计算该股票的盈利状况
  76.         if context.portfolio.positions[security].amount > 0:
  77.             r_ratio=(current_price-current_avgcost)/current_avgcost
  78.         else:
  79.             r_ratio=0
  80.         #卖出股票
  81.         orderfail=order_target(security, 0)
  82.         #统计胜率
  83.         if orderfail!=None:#防止订单无效,如停牌、没钱买等
  84.             winorlose(r_ratio)
  85. #挑选股票
  86. def findstock(context, data):
  87.     #初始化股票列表
  88.     g.buystocks = []
  89.     #循环股票池
  90.     for security in context.stocks:
  91.         # 得到该股票当前价格
  92.         current_price = data[security].price
  93.         #得到五日均价
  94.         avg = data[security].mavg(5)
  95.         #如果当前价格高出五日均线2%则选入
  96.         if current_price>1.02*avg:
  97.             g.buystocks.append(security)
  98.         #如果选出足够的股票则终止挑选
  99.         if len(g.buystocks)==g.max_stock:
  100.             break
  101. #统计胜率,收益为正则判为成功,收益为负则判为失败
  102. def winorlose(r_ratio):
  103.     if r_ratio > 0:
  104.         g.win=g.win+1;
  105.     else:
  106.         g.lose=g.lose+1;
复制代码





回复

使用道具 举报

63

主题

36

回帖

1915

积分

管理员

积分
1915
2019-7-17 23:29:24 显示全部楼层
回复

使用道具 举报

196

主题

140

回帖

1444

积分

管理员

积分
1444
2019-7-17 23:31:04 显示全部楼层
厉害厉害,这个策略不错
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 免费注册
关注微信