连续下跌(更新版)

策略分享
标签: #<Tag:0x00007f61e6acf9f0>

(njchenxin) #1
克隆策略
In [5]:
# 1. 策略基本参数
#抓取数据
df=D.history_data(D.instruments(),start_date='2015-01-01', end_date='2017-05-05', fields=['open', 'high', 'low', 'close'])
df.set_index('date', inplace=True)

# 回测起始时间
start_date = '2015-01-01'
# 回测结束时间
end_date = '2017-05-05'
# 策略比较参考标准,以沪深300为例
benchmark = '000300.INDX'
# 证券池 以贵州茅台为例
instruments =  D.instruments()
# 起始资金
capital_base = 100000

def resample(df):
# https://pandas-docs.github.io/pandas-docs-travis/timeseries.html#offset-aliases
# 周 W、月 M、季度 Q、10天 10D、2周 2W
    period = 'Q'

    year_df = df.resample(period, how='last')
    year_df['open'] = df['open'].resample(period, how='first')
    year_df['high'] = df['high'].resample(period, how='max')
    year_df['low'] = df['low'].resample(period, how='min')
    year_df['close'] = df['close'].resample(period, how='last')
    # 去除空的数据(没有交易的周)
    year_df = year_df[year_df.instrument.notnull()]
    year_df.reset_index(inplace=True)
    return year_df

year_df = df.groupby('instrument').apply(resample)
year_df.reset_index(drop=True, inplace=True)

def seek_stock(df):
    df['pre_open'] = df['open'].shift()
    df['condi_0'] = df['high'] < df['pre_open']
    df['condi_1'] = df['condi_0'].shift(1)
    df['condi_2'] = df['condi_0'].shift(2)
    df['condi_3'] = df['condi_0'].shift(3)
    df['condi_4'] = df['condi_0'].shift(4)
    return df[(df['condi_0'] == True) & (df['condi_1'] == True) & (df['condi_2'] == True) &(df['condi_3'] == True) &(df['condi_4'] == True)]

stock_seeked = year_df.groupby('instrument').apply(seek_stock)
stock_seeked.reset_index(drop=True, inplace=True)

# 2. 策略主体函数
def initialize(context):
    _
    # 设置手续费,买入时万3,卖出是千分之1.3,不足5元以5元计
    context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
    context.hold_periods = 40 # 持有40天,固定持仓期
    context.stock_max_num = 10 # 最大持仓数量
    context.hold_days = {}
    context.daily_buy_stock = list(stock_seeked['instrument'])

# 策略交易逻辑,每个交易日运行一次
def handle_data(context, data):
 
    #筛选股票列表
    date = data.current_dt.strftime('%Y-%m-%d') # 日期

    #买股列表
    stock_can_buy_num = context.stock_max_num 
    stock_to_buy = context.daily_buy_stock
    
    weight =  1 / len(stock_to_buy)

    for stock in stock_to_buy:
        if data.can_trade(context.symbol(stock)):
            curr_position =  context.portfolio.positions['instrument'].amount
            if curr_position == 0:
                for i in list(stock_seeked['date']):
                    if stock_seeked.date < date:# 买入10W股票
                        context.order_target_percent(context.symbol(stock), weight)
        

# 3. 启动回测

# 策略回测接口: https://bigquant.com/docs/strategy_backtest.html
m = M.backtest.v5(
    instruments=instruments,
    start_date=start_date,
    end_date=end_date,
    initialize=initialize,
    handle_data=handle_data,
    # 买入订单以开盘价成交
    order_price_field_buy='open',
    # 卖出订单以开盘价成交
    order_price_field_sell='open',
    capital_base=capital_base,
    benchmark=benchmark,
)
[2017-05-13 10:56:07.828731] INFO: bigquant: backtest.v5 start ..
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-5-72a1f771a274> in <module>()
     90     order_price_field_sell='open',
     91     capital_base=capital_base,
---> 92     benchmark=benchmark,
     93 )

<ipython-input-5-72a1f771a274> in handle_data(context, data)
     72             if curr_position == 0:
     73                 for i in list(stock_seeked['date']):
---> 74                     if stock_seeked.date < date:# 买入10W股票
     75                         context.order_target_percent(context.symbol(stock), weight)
     76 

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

(htly) #2

@njchenxin 我看了你的策略,实现了下,具体代码都有注释,你看看:

克隆策略
In [1]:
# 1. 策略基本参数
#抓取数据
df=D.history_data(D.instruments(),start_date='2015-01-01', end_date='2017-05-05', fields=['open', 'high', 'low', 'close'])
df.set_index('date', inplace=True)

# 回测起始时间
start_date = '2015-01-01'
# 回测结束时间
end_date = '2017-05-05'
# 策略比较参考标准,以沪深300为例
benchmark = '000300.INDX'
# 证券池 以贵州茅台为例
instruments =  D.instruments()
# 起始资金
capital_base = 100000

def resample(df):
# https://pandas-docs.github.io/pandas-docs-travis/timeseries.html#offset-aliases
# 周 W、月 M、季度 Q、10天 10D、2周 2W
    period = 'Q'

    year_df = df.resample(period, how='last')
    year_df['open'] = df['open'].resample(period, how='first')
    year_df['high'] = df['high'].resample(period, how='max')
    year_df['low'] = df['low'].resample(period, how='min')
    year_df['close'] = df['close'].resample(period, how='last')
    # 去除空的数据(没有交易的周)
    year_df = year_df[year_df.instrument.notnull()]
    year_df.reset_index(inplace=True)
    return year_df

year_df = df.groupby('instrument').apply(resample)
year_df.reset_index(drop=True, inplace=True)

def seek_stock(df):
    df['pre_open'] = df['open'].shift()
    df['condi_0'] = df['high'] < df['pre_open']
    df['condi_1'] = df['condi_0'].shift(1)
    df['condi_2'] = df['condi_0'].shift(2)
    df['condi_3'] = df['condi_0'].shift(3)
    df['condi_4'] = df['condi_0'].shift(4)
    return df[(df['condi_0'] == True) & (df['condi_1'] == True) & (df['condi_2'] == True) &(df['condi_3'] == True)] # 注:连续四个季度下跌,连续五个季度符合的股票数据太少了

stock_seeked = year_df.groupby('instrument').apply(seek_stock)
stock_seeked.reset_index(drop=True, inplace=True)
In [34]:
# 整理出每个交易日,买入股票有哪些
daily_buy_stock = stock_seeked.groupby('date').apply(lambda df:list(df.instrument))
In [40]:
# 查看下是个什么东东
daily_buy_stock
Out[40]:
date
2016-06-30     [300226.SZA, 600010.SHA, 600031.SHA, 600208.SHA]
2016-09-30    [000778.SZA, 001896.SZA, 600011.SHA, 600108.SH...
2016-12-31                                         [600645.SHA]
2017-03-31    [000410.SZA, 000526.SZA, 000802.SZA, 002095.SZ...
2017-06-30    [000410.SZA, 000526.SZA, 000802.SZA, 002006.SZ...
dtype: object
In [42]:
# 2. 策略主体函数
def initialize(context):
    
    # 设置手续费,买入时万3,卖出是千分之1.3,不足5元以5元计
    context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
    context.hold_periods = 40 # 持有40天,固定持仓期
    context.stock_max_num = 10 # 最大持仓数量
    
    context.daily_buy_stock = daily_buy_stock
    context.extension = {} # 该变量用来存储股票建仓信息数据

# 策略交易逻辑,每个交易日运行一次
def handle_data(context, data):
 
    date = data.current_dt.strftime('%Y-%m-%d') # 日期
    
    # -------------------------------先处理卖出情形-------------------------------------
    # 达到持有天数,立即卖出
    for e, p in context.portfolio.positions.items():
        if context.trading_day_index - context.extension[e.symbol] >= context.hold_periods: 
            context.order_target(context.symbol(e.symbol), 0)
            # 查看卖出哪些股票
            print('date:', date, '卖出股票:', e.symbol)
            
            
    # --------------------------------再处理买入情形--------------------------------------
    #买股列表
    stock_can_buy_num = context.stock_max_num 
    try:
        stock_to_buy = context.daily_buy_stock[date]
#         print(stock_to_buy)
    except KeyError:
        return
    # 如果当天买入列表有股票,那就买入
    for stock in stock_to_buy:
        curr_position =  context.portfolio.positions[stock].amount
        if curr_position == 0 and data.can_trade(context.symbol(stock)):
            # 等权重
            weight =  1 / len(stock_to_buy)
            context.order_target_percent(context.symbol(stock), weight)
            # 查看买入列表
            print('date:', date, '买入股票:', stock)
            context.extension[stock] = int(context.trading_day_index) # 记录建仓时间
        

# 3. 启动回测
# 策略回测接口: https://bigquant.com/docs/strategy_backtest.html
m = M.backtest.v5(
    instruments=instruments,
    start_date=start_date,
    end_date=end_date,
    initialize=initialize,
    handle_data=handle_data,
    # 买入订单以开盘价成交
    order_price_field_buy='open',
    # 卖出订单以开盘价成交
    order_price_field_sell='open',
    capital_base=capital_base,
    benchmark=benchmark,
)
[2017-05-13 15:12:55.841014] INFO: bigquant: backtest.v5 start ..
['300226.SZA', '600010.SHA', '600031.SHA', '600208.SHA']
date: 2016-06-30 买入股票: 300226.SZA
date: 2016-06-30 买入股票: 600010.SHA
date: 2016-06-30 买入股票: 600031.SHA
date: 2016-06-30 买入股票: 600208.SHA
date: 2016-08-25 卖出股票: 600010.SHA
date: 2016-08-25 卖出股票: 300226.SZA
date: 2016-08-25 卖出股票: 600031.SHA
date: 2016-08-25 卖出股票: 600208.SHA
['000778.SZA', '001896.SZA', '600011.SHA', '600108.SHA', '600307.SHA', '600428.SHA', '600545.SHA', '600787.SHA', '600871.SHA', '601106.SHA', '601766.SHA', '601857.SHA', '601918.SHA', '601991.SHA']
date: 2016-09-30 买入股票: 000778.SZA
date: 2016-09-30 买入股票: 001896.SZA
date: 2016-09-30 买入股票: 600011.SHA
date: 2016-09-30 买入股票: 600108.SHA
date: 2016-09-30 买入股票: 600307.SHA
date: 2016-09-30 买入股票: 600428.SHA
date: 2016-09-30 买入股票: 600787.SHA
date: 2016-09-30 买入股票: 600871.SHA
date: 2016-09-30 买入股票: 601106.SHA
date: 2016-09-30 买入股票: 601766.SHA
date: 2016-09-30 买入股票: 601857.SHA
date: 2016-09-30 买入股票: 601918.SHA
date: 2016-09-30 买入股票: 601991.SHA
date: 2016-12-02 卖出股票: 600011.SHA
date: 2016-12-02 卖出股票: 601991.SHA
date: 2016-12-02 卖出股票: 601918.SHA
date: 2016-12-02 卖出股票: 600787.SHA
date: 2016-12-02 卖出股票: 600871.SHA
date: 2016-12-02 卖出股票: 600307.SHA
date: 2016-12-02 卖出股票: 600108.SHA
date: 2016-12-02 卖出股票: 601106.SHA
date: 2016-12-02 卖出股票: 001896.SZA
date: 2016-12-02 卖出股票: 600428.SHA
date: 2016-12-02 卖出股票: 000778.SZA
date: 2016-12-02 卖出股票: 601857.SHA
date: 2016-12-02 卖出股票: 601766.SHA
['000410.SZA', '000526.SZA', '000802.SZA', '002095.SZA', '002104.SZA', '002161.SZA', '002261.SZA', '002292.SZA', '002506.SZA', '002707.SZA', '002739.SZA', '002741.SZA', '300001.SZA', '300032.SZA', '300079.SZA', '300085.SZA', '300146.SZA', '300168.SZA', '300171.SZA', '300188.SZA', '300333.SZA', '300392.SZA', '300418.SZA', '300431.SZA', '300467.SZA', '600606.SHA', '600645.SHA', '600770.SHA']
date: 2017-03-31 买入股票: 000410.SZA
date: 2017-03-31 买入股票: 000802.SZA
date: 2017-03-31 买入股票: 002095.SZA
date: 2017-03-31 买入股票: 002104.SZA
date: 2017-03-31 买入股票: 002161.SZA
date: 2017-03-31 买入股票: 002261.SZA
date: 2017-03-31 买入股票: 002292.SZA
date: 2017-03-31 买入股票: 002506.SZA
date: 2017-03-31 买入股票: 002707.SZA
date: 2017-03-31 买入股票: 002739.SZA
date: 2017-03-31 买入股票: 002741.SZA
date: 2017-03-31 买入股票: 300001.SZA
date: 2017-03-31 买入股票: 300032.SZA
date: 2017-03-31 买入股票: 300079.SZA
date: 2017-03-31 买入股票: 300085.SZA
date: 2017-03-31 买入股票: 300146.SZA
date: 2017-03-31 买入股票: 300168.SZA
date: 2017-03-31 买入股票: 300171.SZA
date: 2017-03-31 买入股票: 300188.SZA
date: 2017-03-31 买入股票: 300333.SZA
date: 2017-03-31 买入股票: 300418.SZA
date: 2017-03-31 买入股票: 300431.SZA
date: 2017-03-31 买入股票: 600606.SHA
date: 2017-03-31 买入股票: 600770.SHA
[2017-05-13 15:13:51.875680] INFO: Performance: Simulated 569 trading days out of 569.
[2017-05-13 15:13:51.878070] INFO: Performance: first open: 2015-01-05 14:30:00+00:00
[2017-05-13 15:13:51.879383] INFO: Performance: last close: 2017-05-05 19:00:00+00:00
  • 收益率2.67%
  • 年化收益率1.18%
  • 基准收益率-4.28%
  • 阿尔法-0.03
  • 贝塔0.03
  • 夏普比率-0.38
  • 收益波动率8.19%
  • 信息比率0.1
  • 最大回撤11.95%
[2017-05-13 15:13:54.953979] INFO: bigquant: backtest.v5 end [59.112958s].