geek001 发表于 2019-8-24 11:37:34

量化交易策略——相对OBV指标策略

      没有一个指标是完全适用任何时候的,本文并不是提供一种绝对赚钱的策略,有绝对盈利的点,估计也没人拿出来分享,宗旨还是提供一种思路,共同学习。

    OBV指标是葛兰碧于20世纪60年代提出的,并被广泛使用。该指标通过统计成交量变动的趋势来推测股价趋势。OBV以“N”字型为波动单位,并且由许许多多“N”型波构成了OBV的曲线图,对一浪高于一浪的“N”型波,称其为“上升潮”(UP TIDE),至于上升潮中的下跌回落则称为“跌潮”(DOWN FIELD)。OBV能量潮指标是成交量方面研究中相当重要的分析指标之一。1、当股价上升而OBV线下降,表示买盘无力,股价可能会回跌。2、股价下降时而OBV线上升,表示买盘旺盛,逢低接手强股,股价可能会止跌回升。

    其计算公式如下:




其中:
sign=+1 今日vol>昨日vol;
sign=-1 今日vol<昨日vol;
sign=0 今日vol==昨日vol。

    原力(相对OBV)
    定义相对OBV为:


n为时间参数。

    如相对成交量小于下阀值,则为空头信号;如相对成交量大于上阀值,则为多头信号;如相对成交量在上下阀值之间,则为空仓信号,以上是基于相对成交量,给出的多空信号判断。

    下图给出了在上下阀值均为 0.5 时,上证综指的多空信号判断结果,其中1代表多头信号, -1代表空头信号。


原力测试

1.在本策略中不存在卖空,所以当Force等于0或-1时空仓;Force等于1时,开多仓。

2.并未写成多股票的版本,只验证了单只股票。

3.下图为开启大盘止损之后的回测图,分享的回测则为未开启大盘止损的回测图。




源码:


mport talib
from datetime import timedelta, date
import numpy as np

def Force(obv,n):
min_obv = min(obv[-n:-1])
max_obv = max(obv[-n:-1])
r_volume = (obv[-1] - min_obv)/(max_obv - min_obv)
return r_volume
# 600307.XSHG 601988.XSHG

def initialize(context):
    # g.security = get_index_stocks('000300.XSHG')
    g.security = ['600307.XSHG']
    set_universe(g.security)
    set_benchmark('600307.XSHG')
    set_commission(PerTrade(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
    set_slippage(PriceRelatedSlippage())
    g.r_volume_data = 0
    g.type = []
    g.one_day = timedelta(days = 1)
    g.start = context.current_dt.date() - 30*g.one_day

def before_trading_start(context):
    security = g.security
    start = g.start
    end = context.current_dt.date() - g.one_day
    df = get_price(security[-1], start_date=start, end_date=end, frequency='daily', fields=['close','volume','factor'])
    # 剔除停盘数据
    df==0] = np.nan
    df = df.dropna()
    # 回复原始价格
    df['close'] = df['close']/df['factor']
    # 求obv值
    obv = talib.OBV(df['close'].values,double(df['volume'].values))
    # 求相对成交量
    r_volume = Force(obv,10)
   
    # 确定买入卖出信号
    if r_volume>0.5:
      g.r_volume_data = 1
      g.type.append(g.r_volume_data)
    elif r_volume < -0.5:
      g.r_volume_data = -1
      g.type.append(g.r_volume_data)
    else:
      g.r_volume_data = 0
      g.type.append(g.r_volume_data)

def handle_data(context, data):
   
    # ## 止损
    # d = dp_stoploss(kernel=2, n=10, zs=0.03)
    # if d:
    #   if len(context.portfolio.positions)>0:
    #         for stock in list(context.portfolio.positions.keys()):
    #             order_target(stock, 0)
    #   return
   
    security = g.security
    Cash = context.portfolio.cash
    if g.r_volume_data == 1:
      # 买入
      order_value(security[-1],Cash)
    else:
      # 卖出
      order_target(security[-1],0)
      
def dp_stoploss(kernel=2, n=10, zs=0.03):
    '''
    方法1:当大盘N日均线(默认60日)与昨日收盘价构成“死叉”,则发出True信号
    方法2:当大盘N日内跌幅超过zs,则发出True信号
    '''
    # 止损方法1:根据大盘指数N日均线进行止损
    if kernel == 1:
      t = n+2
      hist = attribute_history('000300.XSHG', t, '1d', 'close', df=False)
      temp1 = sum(hist['close'])/float(n)
      temp2 = sum(hist['close'])/float(n)
      close1 = hist['close'][-1]
      close2 = hist['close'][-2]
      if (close2 > temp2) and (close1 < temp1):
            return True
      else:
            return False
    # 止损方法2:根据大盘指数跌幅进行止损
    elif kernel == 2:
      hist1 = attribute_history('000300.XSHG', n, '1d', 'close',df=False)
      if ((1-float(hist1['close'][-1]/hist1['close'])) >= zs):
            return True
      else:
            return False


页: [1]
查看完整版本: 量化交易策略——相对OBV指标策略